-
Notifications
You must be signed in to change notification settings - Fork 1.9k
feat(api): add GitHub integration for sending findings as issues #9732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add complete GitHub integration to Prowler that allows sending security
findings as GitHub Issues, working similarly to the existing Jira integration.
Features:
- GitHub API client with Personal Access Token (PAT) authentication
- Support for creating issues from Prowler findings
- Automatic repository discovery and validation
- Label support for issue categorization
- Rich markdown-formatted issues with detailed finding information
- Full API integration with CRUD operations
- Async task processing for bulk operations
- Connection testing and validation
Implementation:
- Add GitHub API client in prowler/lib/outputs/github/
- Add GitHub to Integration model choices
- Create serializers and validators for GitHub credentials and configuration
- Implement IntegrationGitHubViewSet for API endpoints
- Add async tasks and job processing for sending findings
- Add URL routing for /integrations/{id}/github/dispatches endpoint
API Changes:
- New integration type: "github"
- Credentials: token (required), owner (optional)
- Configuration: repositories dict, owner string
- Dispatch endpoint accepts repository and optional labels
Issue Format:
- Title: [Prowler] SEVERITY - CHECK_ID - RESOURCE_UID
- Body includes: finding details, risk description, recommendations,
remediation code (CLI/Terraform/IaC), resource tags, compliance info
Security:
- GitHub PAT encrypted with Fernet before storage
- Repository access validated before dispatch
- All API calls use HTTPS
- Comprehensive error handling and logging
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
|
✅ Conflict Markers Resolved All conflict markers have been successfully resolved in this pull request. |
|
Please add an entry to the corresponding |
|
|
||
|
|
||
| def initialize_prowler_integration(integration: Integration) -> Jira: | ||
| def initialize_prowler_integration(integration: Integration): |
Check notice
Code scanning / CodeQL
Explicit returns mixed with implicit (fall through) returns
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 days ago
In general, to fix mixed explicit/implicit returns, ensure that every code path ends with an explicit return (either returning a value or None/raising). Here, the function currently returns a client for GitHub and JIRA, and implicitly returns None for other integration types or future additions. The safest, most explicit fix without changing existing successful behavior is to add a final return None at the end of the function. This preserves current semantics (callers that previously got None still get None) but makes the intent and return type consistent and removes the implicit fall-through. No extra imports or helper methods are needed; we only add a single explicit return None before the end of initialize_prowler_integration in api/src/backend/api/utils.py.
-
Copy modified line R436 -
Copy modified lines R449-R450
| @@ -433,6 +433,7 @@ | ||
| integration.configuration["repositories"] = {} | ||
| integration.connected = False | ||
| integration.connection_last_checked_at = datetime.now(tz=timezone.utc) | ||
| integration.connection_last_checked_at = datetime.now(tz=timezone.utc) | ||
| integration.save() | ||
| raise github_auth_error | ||
| elif integration.integration_type == Integration.IntegrationChoices.JIRA: | ||
| @@ -445,3 +446,5 @@ | ||
| integration.connection_last_checked_at = datetime.now(tz=timezone.utc) | ||
| integration.save() | ||
| raise jira_auth_error | ||
|
|
||
| return None |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #9732 +/- ##
==========================================
- Coverage 92.46% 86.49% -5.98%
==========================================
Files 160 277 +117
Lines 22814 30139 +7325
==========================================
+ Hits 21096 26069 +4973
- Misses 1718 4070 +2352
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
🔒 Container Security ScanImage: 📊 Vulnerability Summary
10 package(s) affected
|
Add complete frontend implementation for GitHub integration following the same pattern as Jira integration. Components: - GitHubIntegrationForm: Form for creating/editing GitHub integrations - GitHubIntegrationsManager: Manager component for listing and managing integrations - GitHubIntegrationCard: Card component for main integrations page - GitHub integration page at /integrations/github Features: - Personal Access Token input with validation - Optional repository owner filter - Connection testing and repository discovery - Enable/disable integration toggle - Edit credentials functionality - Delete integration with confirmation - Pagination support - Integration status display with last checked timestamp Server Actions: - getGitHubIntegrations(): Fetch enabled GitHub integrations - sendFindingToGitHub(): Send finding to GitHub as issue - pollGitHubDispatchTask(): Poll async task completion Types & Schemas: - githubIntegrationFormSchema: Zod schema for creation - editGitHubIntegrationFormSchema: Zod schema for editing - GitHubCredentialsPayload: TypeScript interface for credentials - GitHubDispatchRequest/Response: API types for dispatching Integration Page: - Created /integrations/github page with features list - Added GitHub card to main integrations overview - Exported GitHub components from integrations index 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
| const response = await fetch(url.toString(), { | ||
| method: "POST", | ||
| headers, | ||
| body: JSON.stringify(payload), | ||
| }); |
Check failure
Code scanning / CodeQL
Server-side request forgery Critical
URL
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 days ago
In general, to fix this type of issue you constrain user-controlled values before incorporating them into request URLs. You either (a) map them to known safe constants (allow‑list) or (b) strictly validate them against an expected format and reject or sanitize anything that doesn’t conform. For path segments, you must prevent path traversal (../), slashes, and other characters that could alter the intended endpoint.
For this specific case, the best minimal fix without changing existing functionality is to validate integrationId against a strict pattern of allowed characters before building the URL. A typical approach is to allow only URL-safe identifier characters such as letters, digits, hyphens, and underscores, and reject anything else. If the value fails validation, we return an error before making the request. This confines the request to the intended /integrations/{safe-id}/github/dispatches path and prevents manipulation like embedding slashes or .. segments.
Implementation details within ui/actions/integrations/github-dispatch.ts:
- Add a small helper function (inside this file) that checks
integrationIdwith a regular expression such as/^[A-Za-z0-9_-]+$/. If it doesn’t match, the function should returnfalse. - At the beginning of
sendFindingToGitHub, use this helper to validateintegrationId. If invalid, immediately return{ success: false, error: "Invalid integration ID" }(or similar) instead of continuing. - Keep the rest of the logic unchanged:
apiBaseUrlcontinues to define the host, andintegrationIdis only used once it is known to match the safe pattern.
No new imports are needed; we can implement validation using built‑in JavaScript/TypeScript capabilities.
-
Copy modified lines R76-R85
| @@ -73,6 +73,16 @@ | ||
| | { success: true; taskId: string; message: string } | ||
| | { success: false; error: string } | ||
| > => { | ||
| // Validate integrationId to avoid using unsafe path segments in the request URL | ||
| // Allow only URL-safe identifier characters (letters, digits, underscores, hyphens). | ||
| const integrationIdIsValid = /^[A-Za-z0-9_-]+$/.test(integrationId); | ||
| if (!integrationIdIsValid) { | ||
| return { | ||
| success: false, | ||
| error: "Invalid integration ID", | ||
| }; | ||
| } | ||
|
|
||
| const headers = await getAuthHeaders({ contentType: true }); | ||
| const url = new URL( | ||
| `${apiBaseUrl}/integrations/${integrationId}/github/dispatches`, |
🔒 Container Security ScanImage: 📊 Vulnerability Summary
3 package(s) affected
|
|
I'm closing this as requested. We'll work on this once prioritised. |
Context
Prowler currently supports sending security findings to Jira, but many teams use GitHub Issues for tracking security vulnerabilities and remediation tasks. This PR adds a complete GitHub integration that allows users to send Prowler findings as GitHub Issues, following the same pattern as the existing Jira integration.
Description
This PR implements a full-featured GitHub integration that creates GitHub Issues from Prowler security findings. The integration uses GitHub Personal Access Tokens (PAT) for authentication and provides a seamless experience similar to the existing Jira integration.
Key Features:
GitHub API Client:
API Integration:
"github"UI Components:
Security:
Issue Format:
[Prowler] SEVERITY - CHECK_ID - RESOURCE_UIDChanges Include:
New Backend Files:
prowler/lib/outputs/github/github.py- Main GitHub API client classprowler/lib/outputs/github/exceptions/exceptions.py- Custom exception classesprowler/lib/outputs/github/__init__.py- Package exportsprowler/lib/outputs/github/exceptions/__init__.py- Exception exportsModified Backend Files:
api/src/backend/api/models.py- Add GitHub to Integration choicesapi/src/backend/api/utils.py- Add GitHub integration initialization and connection testingapi/src/backend/api/filters.py- Add IntegrationGitHubFindingsFilterapi/src/backend/api/v1/serializer_utils/integrations.py- Add GitHub serializersapi/src/backend/api/v1/serializers.py- Add GitHub dispatch serializer and validationapi/src/backend/api/v1/urls.py- Add GitHub integration routingapi/src/backend/api/v1/views.py- Add IntegrationGitHubViewSetapi/src/backend/tasks/tasks.py- Add github_integration_taskapi/src/backend/tasks/jobs/integrations.py- Add send_findings_to_github jobNew UI Files:
ui/components/integrations/github/github-integration-form.tsx- Form componentui/components/integrations/github/github-integrations-manager.tsx- Manager componentui/components/integrations/github/github-integration-card.tsx- Card componentui/actions/integrations/github-dispatch.ts- Server actions for dispatchui/app/(prowler)/integrations/github/page.tsx- GitHub integrations pageui/types/integrations.ts- Added GitHub schemas and typesModified UI Files:
ui/components/integrations/index.ts- Export GitHub componentsui/app/(prowler)/integrations/page.tsx- Add GitHub integration cardAPI Endpoints
Create GitHub Integration:
Test Connection:
Send Findings to GitHub:
Steps to Review
Review GitHub API Client (
prowler/lib/outputs/github/github.py):Review Backend Integration:
api/models.pyapi/v1/serializer_utils/integrations.pyapi/v1/views.pyapi/v1/urls.pyReview Async Tasks:
tasks/tasks.pytasks/jobs/integrations.pyapi/utils.pyReview UI Components:
ui/components/integrations/github/github-integration-form.tsxui/components/integrations/github/github-integrations-manager.tsxui/components/integrations/github/github-integration-card.tsxui/actions/integrations/github-dispatch.tsui/app/(prowler)/integrations/github/page.tsxReview Security:
Testing Checklist
Backend:
UI:
Checklist
UI
API
Implementation Summary
Backend (13 files changed, ~1,070 lines added):
UI (8 files changed, ~928 lines added):
/integrations/githubTotal: 21 files changed, ~2,000 lines added
Next Steps
License
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.